package smlab.view.ui.dragAndDrop
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import smlab.motion.TweenLite;
	import smlab.utils.AddToFavoriteUtil;
	import smlab.utils.DisplayObjectUtil;
	
	/**
	 * 可拖动粘附的显示对象
	 * @author simon
	 * 
	 */
	public class DragAndDropTile extends Sprite implements IDragAndDrop
	{
		public static const COPY_SKIN_TYPE_BMP:uint=0;
		public static const COPY_SKIN_TYPE_SKIN:uint=1;
		public static const COPY_SKIN_TYPE_NONE:uint=2;
		
		private var skin_:DisplayObject;
		private var data_:Object;
		private var oldPoint_:Point;
		private var container_:DisplayObjectContainer;
		private var parentContainer_:DisplayObjectContainer;//原本的父级容器（被鼠标拖拽前的父级容器）
		private var itemID_:uint;
		private var copySkinType_:uint=1;
		private var isLock_:Boolean=true;
		private var isDraging_:Boolean=false;//是否正在被拖动
		private var dragType_:uint=1;//拖动方式：1-鼠标Down的时候开始拖动；2-鼠标Click的时候拖动;3-Down或Click都拖动
		private var mouseDownTime:uint;//记录鼠标点击时的系统时间
		private var mouseUpTime:uint;//记录鼠标弹起时的系统时间
		
		public function DragAndDropTile()
		{
			super();
			container_=new Sprite;
			addChild(container_);
			addEventListener(Event.ADDED_TO_STAGE,onAddToStage);
			isLock=true;
		}
		
		public function get skin():DisplayObject
		{
			return skin_;
		}
		
		/**
		 * 设置 UI。UI 会被 addChild 到 Tile
		 * @param d
		 * 
		 */
		public function set skin(d:DisplayObject):void
		{
			if(d){
				skin_=d;
				DisplayObjectUtil.removeAllChild(container_);
				container_.addChild(skin_);
				this.cacheAsBitmap=true;
			}
			
		}
		
		public function set oldPoint(p:Point):void
		{
			oldPoint_=p;
		}
		
		public function get oldPoint():Point
		{
			return oldPoint_;
		}
		
		public function drop(ui:DisplayObject,data:Object):void
		{
			if(isLock==false){
				var p:Point=DisplayObjectUtil.getGlobalPoint(ui);
				p=DisplayObjectUtil.getLocalPoint(this.container_,p);
				ui.x=p.x;
				ui.y=p.y;
				this.skin=ui;
				TweenLite.to(this.skin,0.2,{x:0,y:0});
				this.data=data;
			}
		}
		
		public function get copySkinType():uint
		{
			return copySkinType_;
		}
		
		public function set copySkinType(n:uint):void
		{
			copySkinType_=n;
		}
		
		public function get isLock():Boolean
		{
			return isLock_;
		}
		
		public function set isLock(b:Boolean):void
		{
			isLock_=b;
			
			if(isLock_){
				removeMouseEvent();
			}else{
				addMouseEvent();
			}
		}
		
		public function get isDraging():Boolean
		{
			return isDraging_;
		}
		
		public function set isDraging(b:Boolean):void
		{
			isDraging_=b;
		}
		
		public function get dragType():uint
		{
			return dragType_;
		}
		
		public function set dragType(b:uint):void
		{
			dragType_=b;
		}
		
		public function get skinBMP():Bitmap
		{
			var bd:BitmapData=new BitmapData(skinContainer.width,skinContainer.height);
			bd.draw(skinContainer);
			var bmp:Bitmap=new Bitmap(bd);
			return bmp;
		}
		
		public function get data():Object
		{
			return data_;
		}
		
		public function set data(obj:Object):void
		{
			data_=obj;
		}
		
		public function get skinContainer():DisplayObjectContainer
		{
			return container_;
		}
		
		public function set parentContainer(d:DisplayObjectContainer):void
		{
			parentContainer_=d;
		}
		
		public function get parentContainer():DisplayObjectContainer
		{
			return parentContainer_;
		}
		
		public function get itemID():uint
		{
			return itemID_;
		}
		
		public function set itemID(type:uint):void
		{
			itemID_=type;
		}
		
		private function onAddToStage(e:Event):void
		{
			parentContainer=this.parent
		}
		
		private function startDragFun():void
		{
			parentContainer=this.parent;
			oldPoint=new Point(this.x,this.y);
			var stagePoint:Point=DisplayObjectUtil.getGlobalPoint(this);
			this.x=stagePoint.x;
			this.y=stagePoint.y;
			stage.addChild(this);
			forbitMouse();
			this.startDrag();
		}
		
		private function stopDragFun():void
		{
			this.stopDrag();
			rebound();
			regainMouse();
		}
		
		private function forbitMouse():void{
			this.mouseEnabled=false;
			this.mouseChildren=false
		}
		
		/**
		 * 恢复鼠标可用
		 * 
		 */
		private function regainMouse():void{
			this.mouseEnabled=true;
			this.mouseChildren=true;
		}
		
		private function onMouseOut(e:*):void{
			stopDragFun();
		}
		
		private function onMouseDown(e:MouseEvent):void
		{
			var t:Date=new Date;
			mouseDownTime=t.getTime();
			
			if(dragType==1 || dragType==3){
				startDragFun();
			}
		}
		
		private function onMouseUp(e:MouseEvent):void
		{
			e.stopImmediatePropagation();
			
			var t:Date=new Date;
			mouseUpTime=t.getTime();
			var gap:uint=mouseUpTime-mouseDownTime;
			
			if(gap<400){
				if(dragType==2 || dragType==3){
					startDragFun();
					return;
				}
			}
			
			regainMouse();
			var isDoRelease:Boolean=false;//被释放并且被接收
			
			if(this.stage)
			{
				var stageMousePoint:Point=new Point(stage.mouseX,stage.mouseY);
				var a:Array=stage.getObjectsUnderPoint(stageMousePoint);
				
				for(var i:int=0;i<a.length;i++){
					var o:DisplayObject=a[i];
					var targetObject:DisplayObject=o.parent.parent;
					
					if(targetObject is IDragAndDrop)
					{
						var targetIdrag:IDragAndDrop=IDragAndDrop(targetObject);
						
						if(!targetIdrag.itemID || !this.itemID){
							return;
						}
						
						if(targetIdrag.itemID==this.itemID)
						{
							if(targetIdrag.isLock){
								return;
							}
							
							switch(copySkinType){
								case COPY_SKIN_TYPE_BMP:
									targetIdrag.drop(this.skinBMP,this.data);
									break;
								case COPY_SKIN_TYPE_SKIN:
									targetIdrag.drop(this.skin,this.data);
									break;
								case COPY_SKIN_TYPE_NONE:
									targetIdrag.drop(null,this.data);
									break;
							}
							
							this.stopDrag();
							remove();
							isDoRelease=true;
						}
					}
				}
			}
			
			if(isDoRelease==false){
				rebound();
			}
			
			this.stopDrag();
		}
		
		/**
		 * 弹回原地
		 * 
		 */
		public function rebound():void
		{
			parentContainer.addChild(this);
			
			if(oldPoint){
				TweenLite.to(this,0.4,{x:oldPoint.x,y:oldPoint.y});
			}
		}
		
		private function addMouseEvent():void
		{
//			this.addEventListener(MouseEvent.CLICK,onMouseClick);
			this.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
			
			if(stage){
				stage.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
//				stage.addEventListener(MouseEvent.MOUSE_OUT,onMouseOut);
//				stage.addEventListener(Event.MOUSE_LEAVE,onMouseOut);
//				stage.addEventListener(FocusEvent.FOCUS_OUT,onMouseOut);
			}
		}
		
		private function removeMouseEvent():void
		{
			this.removeEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
			
			if(stage){
				stage.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp);
				stage.removeEventListener(MouseEvent.MOUSE_OUT,onMouseOut);
				stage.removeEventListener(Event.MOUSE_LEAVE,onMouseOut);
				stage.removeEventListener(FocusEvent.FOCUS_OUT,onMouseOut);
			}
		}
		
		public function remove():void
		{
			skin_=null;
			data_=null;
			DisplayObjectUtil.removeAllChild(container_);
			container_=null;
			removeMouseEvent();
			DisplayObjectUtil.removeFromParent(this);
		}
	}
}